package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.atguigu.tingshu.album.AlbumFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private WxMaService wxMaService;

	@Autowired
	private RedisTemplate redisTemplate;
	@Autowired
	private RabbitService rabbitService;

	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;

	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;

	@Autowired
	private MongoTemplate mongoTemplate;

	@Autowired
	private UserVipServiceMapper userVipServiceMapper;

	@Autowired
	private VipServiceConfigMapper vipServiceConfigMapper;

	@Autowired
	private AlbumFeignClient albumFeignClient;



	/**
	 * 微信登录
	 * @param code
	 * @return
	 */
	@Override
	@SneakyThrows
	public Map<String, String> wxLogin(String code) {
		//通过第三方工具向微信发送http请求
		WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);

		//获取微信唯一标识
		String openid = sessionInfo.getOpenid();

		if(openid ==null){
			throw  new GuiguException(250,"微信授权失败 请重试");
		}

		UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));


		//判断用户是否第一次注册
		if(userInfo ==null){
			//第一次登录 需要初始化信息

			//用户表的新增
			 userInfo = new UserInfo();
			userInfo.setWxOpenId(openid);
			userInfo.setNickname("听书人：" +openid);
			userInfo.setAvatarUrl("http://192.168.254.156:9000/sph/2024-06-18/d4fa55cb-f4fb-4096-bd88-cfe9e607417d.jpeg");
			userInfo.setIsVip(0);
			userInfo.setStatus("1");
			userInfoMapper.insert(userInfo);

			//userInfoVo = BeanUtil.copyProperties(userInfo1, UserInfoVo.class);

			// TODO  远程解耦调用   初始化用户账户信息用户账号 用户账号明细两张表
			rabbitService.sendMessage(MqConst.EXCHANGE_USER,MqConst.ROUTING_USER_REGISTER,userInfo.getId());
		}
		//不是第一次返回token
		String token = IdUtil.fastUUID();
		//将用户信息放到缓存里面去
		String loginKey= RedisConstant.USER_LOGIN_KEY_PREFIX + token;
		UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
		//要使用userIndoVo 是为了redis中吧缓存密码
		redisTemplate.opsForValue().set(loginKey,userInfoVo,30, TimeUnit.MINUTES);

		//返回给前端token
		HashMap<String, String> map = new HashMap<>();
		map.put("token",token);


		return map;
	}


	/**
	 * 获取登陆用户信息
	 * @param token
	 * @return
	 */
	@Override
	public UserInfoVo getUserInfo(String token) {
		String loginKey= RedisConstant.USER_LOGIN_KEY_PREFIX + token;
		UserInfoVo userinfoVo  = (UserInfoVo) redisTemplate.opsForValue().get(loginKey);
		return userinfoVo;
	}


	/**
	 * 获取用户声音列表付费情况
	 * @param userId
	 * @param albumId
	 * @param needChackTrackIdList 需要验证的专辑id
	 * @return
	 */
	@Override
	public Map<Long, Integer> userIsPaidTrack(Long userId, Long albumId, List<Long> needChackTrackIdList) {

		//看看是否购买了专辑 购买了专辑 直接都返回1
		Long aLong = userPaidAlbumMapper.selectCount(new LambdaQueryWrapper<UserPaidAlbum>()
				.eq(UserPaidAlbum::getAlbumId, albumId).
				eq(UserPaidAlbum::getUserId, userId));
		if(aLong !=0){
			HashMap<Long, Integer> map = new HashMap<>();
			needChackTrackIdList.forEach(trackId -> {
				map.put(trackId,1);
			});
			return map;
		}

		//看看购买了那些声音
		List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
				.eq(UserPaidTrack::getUserId, userId)
				.eq(UserPaidTrack::getAlbumId, albumId));

		if(CollectionUtils.isEmpty(userPaidTracks)){
			HashMap<Long, Integer> map = new HashMap<>();
			//也没有购买专辑的声音
			needChackTrackIdList.forEach(trackId -> {
				map.put(trackId,0);
			});
			return map;

		}else {
			//有购买专辑
			List<Long> TrackIdList = userPaidTracks.stream().map(userPaidTrack ->
					userPaidTrack.getTrackId()).collect(Collectors.toList());

			HashMap<Long, Integer> map = new HashMap<>();
			needChackTrackIdList.stream().forEach(aLong1 -> {

				if(TrackIdList.contains(aLong1)){
					map.put(aLong1,1);
				}else {
					map.put(aLong1,0);
				}
			});

			return map;
		}

	}

	/**
	 * 修改当前登录用户基本信息
	 * @param userInfoVo
	 */
	@Override
	@SneakyThrows
	public void updateUser(UserInfoVo userInfoVo ,String token) {
		Long userId = AuthContextHolder.getUserId();
		userInfoVo.setId(userId);

		UserInfo userInfo = BeanUtil.copyProperties(userInfoVo, UserInfo.class);

		String loginKey= RedisConstant.USER_LOGIN_KEY_PREFIX + token;
		//修改之前删除reids
		redisTemplate.delete(loginKey);

		//修改基本信息
		userInfoMapper.updateById(userInfo);

		//防止多线程 再次添加
		Thread.sleep(300);
		redisTemplate.delete(loginKey);


		//更新数据库
		UserInfoVo userInfoVo1 = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
		redisTemplate.opsForValue().set(loginKey,userInfoVo1,RedisConstant.USER_LOGIN_KEY_TIMEOUT,TimeUnit.SECONDS);
	}

	/**
	 * 获取用户最近一次播放记录
	 * @return
	 */
	@Override
	public Map<String, Long> getLatelyTrack() {
		Map<String, Long> map = new HashMap<>();
		//设置默认值
		map.put("albumId", 1577l);
		map.put("trackId", 51925l);

		Long userId = AuthContextHolder.getUserId();
		if(userId!=null){
			Query query = new Query();
			//条件
			query.addCriteria(Criteria.where("userId").is(userId));
			query.with(Sort.by(Sort.Direction.DESC,"updateTime"));
			query.limit(1);

			UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId));
			if(userListenProcess!=null){
				map.put("albumId",userListenProcess.getAlbumId());
				map.put("trackId",userListenProcess.getTrackId());
				return map;
			}

		}
		return map;
	}

	/**
	 * 根据专辑id+用户ID获取用户已购买声音id列表
	 * @param albumId
	 * @param userId
	 * @return
	 */
	@Override
	public List<Long> findUserPaidTrackList(Long albumId, Long userId) {

		List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
				.eq(UserPaidTrack::getAlbumId, albumId)
				.eq(UserPaidTrack::getUserId, userId)
				.select(UserPaidTrack::getTrackId));
		if(CollectionUtils.isNotEmpty(userPaidTracks)){
			List<Long> longList = userPaidTracks.stream().map(userPaidTrack -> userPaidTrack.getTrackId()).collect(Collectors.toList());
			return longList;
		}
		return null;

	}

	/**
	 * 处理用户的购买记录
	 * @param userPaidRecordVo
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
		//根据类型判断用户购买的是声音 专辑还是会员
		if(userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_VIP)){
			//vip
			UserVipService userVipService = new UserVipService();


			//判断用户是否是vip
			UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
			Integer isVip = userInfo.getIsVip();
			//vip 只能购买一个
			Long aLong = userPaidRecordVo.getItemIdList().get(0);
			//根据id查询vip套餐
			VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(aLong);
			//用户所购买的服务月份
			Integer serviceMonth = vipServiceConfig.getServiceMonth();
			if(isVip.intValue() ==1){
				//用户是vip 续期
				//vip生效时候是用户的vip到期时间
				userVipService.setStartTime(userInfo.getVipExpireTime());

				//到期时间vip到期时间加上用户的新增vip的时间
				userVipService.setExpireTime(DateUtil.offsetMonth(userInfo.getVipExpireTime(), serviceMonth));

			}else if(isVip.intValue()==0){
				//新增用户的vip
				userVipService.setStartTime(new Date());
				userVipService.setExpireTime(DateUtil.offsetMonth(new Date(), serviceMonth));
			}

			//填充数据
			userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
			userVipService.setUserId(userPaidRecordVo.getUserId());
			userVipService.setIsAutoRenew(0);
			userVipServiceMapper.insert(userVipService);
			//要更新用户表的会员状态为1 服务状态
			userInfo.setIsVip(1);
			userInfo.setVipExpireTime(userVipService.getExpireTime());
			userInfoMapper.updateById(userInfo);
		}else if(userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_TRACK)){
			//是否已经新增过了声音
			Long aLong = userPaidTrackMapper.selectCount(new LambdaQueryWrapper<UserPaidTrack>()
					.eq(UserPaidTrack::getOrderNo, userPaidRecordVo.getOrderNo()));
			if(aLong <0){
				return;
			}

			List<Long> itemIdList = userPaidRecordVo.getItemIdList();
			//获取专辑的id
			Result<TrackInfo> trackInfo = albumFeignClient.getTrackInfo(itemIdList.get(0));
			Assert.notNull(trackInfo,"远程获取声音降级");
			for (Long aLong1 : itemIdList) {
				//声音
				UserPaidTrack userPaidTrack = new UserPaidTrack();

				userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
				userPaidTrack.setUserId(userPaidRecordVo.getUserId());
				userPaidTrack.setTrackId(aLong1);
				userPaidTrack.setAlbumId(trackInfo.getData().getAlbumId());
				userPaidTrackMapper.insert(userPaidTrack);
			}


		}else if(userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_ALBUM)){
			//判断是否已经新增过了 --利用流水号唯一
			Long aLong = userPaidAlbumMapper.selectCount(new LambdaQueryWrapper<UserPaidAlbum>()
					.eq(UserPaidAlbum::getOrderNo, userPaidRecordVo.getOrderNo()));
			if(aLong<0){
				return;
			}

			//专辑
			UserPaidAlbum userPaidAlbum = new UserPaidAlbum();

			//封装数据
			userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
			userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
			userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
			userPaidAlbumMapper.insert(userPaidAlbum);
		}

	}
}
